import java.io.*;

public class Parser
{
	
	public Parser(){
	
	}

	/*
	The function condition is for the parsing of the condition statements in the code.
	*/
	public static int parse(data dat,Lexer lex)
	{
		StringBuffer temp2= new StringBuffer("a");
		StringBuffer temp= new StringBuffer("#");
		int error =0;
		int flag=0;
		
		
		while(!dat.token.toString().equalsIgnoreCase(temp.toString()))			//loops uptil the file ends
		{
			dat.token = lex.lexer(dat);							//reading tokens from source file one by one
			flag=0;
			
			/*
			Here the parsing of code starts.
			We are doing top-down predictive parsing. We start from first token and predict the
			value of next token according to the syntax of grammer.
			*/
			
			if((dat.code == 2)&&(dat.token.toString().equalsIgnoreCase("INPUT")))		
			{
				dat.token = lex.lexer(dat);
				{
					if(dat.code ==3)
					{
						for(int x=0;x<dat.var_count;x++)
							if(dat.variables[x].toString().equals(dat.token.toString()))
								flag=1;
						if(flag==0){
							dat.variables[dat.var_count]=dat.token;
							dat.var_count++;
						}
						dat.token = lex.lexer(dat);
						if((dat.code ==6 )&&(dat.token.toString().equalsIgnoreCase(";")))
						{
							//System.out.println("this is correct format in line "+line_no);
						}
						else
						{
							System.out.println("Semicolon expected in line "+dat.line_no);
							do{
								dat.token = lex.lexer(dat);
							}while(!dat.token.toString().equals(";"));
							error=1;
						}
					}
					else
					{
						System.out.println("identifier expected in line "+dat.line_no);
						do{
								dat.token = lex.lexer(dat);
							}while(!dat.token.toString().equals(";"));
							error=1;
					}
				}
			}
			else
			{
				if((dat.code == 2)&&(dat.token.toString().equalsIgnoreCase("OUTPUT")))
				{
					dat.token = lex.lexer(dat);
					{
						if((dat.code==6)&&(dat.token.toString().equalsIgnoreCase("\"")))
						{
							dat.token = lex.lexer(dat);
							
							do
							{
								dat.token = lex.lexer(dat);
							}while(!dat.token.toString().equalsIgnoreCase("\""));
							dat.token = lex.lexer(dat);
							
						}
						else
						{	
							expression(dat,lex);
						}
						if((dat.code == 6)&&(dat.token.toString().equalsIgnoreCase(";")))
							{
								//System.out.println("this is correct format in line "+dat.line_no+dat.token);
							}
						else
							{
								System.out.println("Semicolon expected in line  "+dat.line_no);
								do{
									dat.token = lex.lexer(dat);
								}while(!dat.token.toString().equals(";"));
								error=1;
							}
					}
				}
				else
				{
					if((dat.code == 2)&&(dat.token.toString().equalsIgnoreCase("GOTO")))
					{
						dat.token = lex.lexer(dat);
						{
							if((dat.code ==3)||(dat.code ==1))
							{
								dat.token = lex.lexer(dat);
								if((dat.code ==6)&&(dat.token.toString().equalsIgnoreCase(";")))
								{
									//System.out.println("this is correct format in line "+line_no+token);
								}
								else
								{
									System.out.println("Semicolon expected in line "+dat.line_no);
									do{
										dat.token = lex.lexer(dat);
									}while(!dat.token.toString().equals(";"));
									error=1;
								}
							}
							else
							{
								System.out.println("identifier expected in line "+dat.line_no);
								do{
									dat.token = lex.lexer(dat);
								}while(!dat.token.toString().equals(";"));
								error=1;
							}
						}	
					}
					else
					{
						if((dat.code ==2)&&(dat.token.toString().equalsIgnoreCase("IF")))
						{	
							
							dat.token = lex.lexer(dat);
							condition(dat,lex);
							if((dat.code ==2)&&(dat.token.toString().equalsIgnoreCase("GOTO")))
							{
								dat.token = lex.lexer(dat);
								{
									//System.out.println(token);
									if((dat.code ==3)||(dat.code ==1))
									{
										dat.token = lex.lexer(dat);
										//System.out.println(token);
										if((dat.code ==6)&&(dat.token.toString().equalsIgnoreCase(";")))
										{
											//System.out.println("this is correct format after full chk "+line_no);
										}
										else
										{
											System.out.println("Semicolon expected in line "+dat.line_no);
											do{
												dat.token = lex.lexer(dat);
											}while(!dat.token.toString().equals(";"));
											error=1;
										}
									}
									else
									{
										System.out.println("identifier expected in line "+dat.line_no);
										do{
											dat.token = lex.lexer(dat);
										}while(!dat.token.toString().equals(";"));
										error=1;
									}
								}	
							}
						}
						else
						{
							if(dat.code == 3)
							{
							
								/* write here for assignment statement*/
								temp2 = dat.token;
								dat.token = lex.lexer(dat);
								if((dat.code == 5)&&(dat.token.toString().equalsIgnoreCase("=")))
								{
									for(int x=0;x<dat.var_count;x++)
									if(dat.variables[x].toString().equals(temp2.toString()))
									flag=1;
									if(flag==0)
									{
										dat.variables[dat.var_count]=temp2;
										dat.var_count++;
									}
									dat.token = lex.lexer(dat);
									expression(dat,lex);
									//System.out.println(token);
									if((dat.code == 6)&&(dat.token.toString().equalsIgnoreCase(";")))
									{
										//System.out.println("the assignment is fine  in line "+line_no);
									}
									else
									{
										System.out.println("Semicolon expected at the end of line "+dat.line_no);
										do{
											dat.token = lex.lexer(dat);
										}while(!dat.token.toString().equals(";"));
										error=1;
									}
								}
								
								else
								{
									if((dat.code ==6)&&(dat.token.toString().equalsIgnoreCase(":")))
									{
										
									}
								
								
									else
									{
										System.out.println("Assignment operator is missing in line "+dat.line_no);
										do{
											dat.token = lex.lexer(dat);
										}while(!dat.token.toString().equals(";"));
										error=1;
									}
								}
							}
							else
							{

								if(dat.token.toString().equalsIgnoreCase("/"))
								{
									dat.token = lex.lexer(dat);
									if((dat.code==4)&&(dat.token.toString().equalsIgnoreCase("*")))
									{
										do
										{
											dat.token = lex.lexer(dat);
										}while(!dat.token.toString().equalsIgnoreCase("*"));
										dat.token = lex.lexer(dat);
										
										if(!dat.token.toString().equalsIgnoreCase("/"))
										{
											System.out.println("the comment is not ended properly");
											do{
												dat.token = lex.lexer(dat);
											}while(!dat.token.toString().equals(";"));
											error=1;
										}
									}
									else
									{
										System.out.println("Error-statement not begin with backslash "+dat.line_no);	
										do{
											dat.token = lex.lexer(dat);
										}while(!dat.token.toString().equals(";"));
										error=1;
									}
									
								}							
								else
								{		
									if(dat.token.toString().equalsIgnoreCase("#"))
									{
									}
									else
									{
										System.out.println("Error- statement should begin with identifier or keyword "+dat.line_no+"\t"+dat.token);		
										do{
											dat.token = lex.lexer(dat);
										}while(!dat.token.toString().equals(";"));
										error=1;
									}
								}
							}
							
						}
					}
				}
			}
			
		}
	
	return error;
	
	}
	
	
	
	public static void condition(data dat,Lexer lex)
	{
		if((dat.code == 6)&&(dat.token.toString().equalsIgnoreCase("(")))
		{
			
			dat.token = lex.lexer(dat);
			
			expression(dat,lex);
			if((dat.token.toString().equalsIgnoreCase(">"))||(dat.token.toString().equalsIgnoreCase("<"))||(dat.token.toString().equalsIgnoreCase("!="))||(dat.token.toString().equalsIgnoreCase(">="))||(dat.token.toString().equalsIgnoreCase("<="))||(dat.token.toString().equalsIgnoreCase("=")))
			{
				
				dat.token = lex.lexer(dat);
				
				expression(dat,lex);
				if((dat.code == 6)&&(dat.token.toString().equalsIgnoreCase(")")))				{
					//System.out.println("The syntax is fine after condition"+dat.line_no);
					dat.token = lex.lexer(dat);				}
				else
				{
					System.out.println("Closing bracket expected in line "+dat.line_no);
					do{
						dat.token = lex.lexer(dat);
					}while(!dat.token.toString().equals(";"));
				}
			}
			else
			{
				System.out.println("operator expected in lino "+dat.line_no);
				do{
					dat.token = lex.lexer(dat);
				}while(!dat.token.toString().equals(";"));
			}
		}
		else
		{
			System.out.println("opening bracket expected in lino "+dat.line_no);
			do{
				dat.token = lex.lexer(dat);
			}while(!dat.token.toString().equals(";"));		}
	}
	
	/*
	
	The function expression is for the parsing of the expressions in the code.
	 
	*/
	public static void expression(data dat,Lexer lex)
	{
		int flag=0;
		if((dat.code ==6)&&(dat.token.toString().equalsIgnoreCase("(")))
		{
			dat.token = lex.lexer(dat);
			//System.out.println(dat.token);
			expression(dat,lex);
			if((dat.code == 6)&&(dat.token.toString().equalsIgnoreCase(")")))
			{
				//System.out.println("The syntax is fine "+dat.line_no);
				dat.token = lex.lexer(dat);
			}
			else			{
				System.out.println("Closing bracket expected in line "+dat.line_no);
				do{
					dat.token = lex.lexer(dat);
				}while(!dat.token.toString().equals(";"));			}
		}
		else
		{
			if((dat.code==3)||(dat.code==1))
			{
				if(dat.code==3)
				{
					for(int x=0;x<dat.var_count;x++)
					if(dat.variables[x].toString().equals(dat.token.toString()))
					flag=1;
					if(flag==0)
					{
						dat.variables[dat.var_count]=dat.token;
						dat.var_count++;
					}
				}
				dat.token = lex.lexer(dat);
				
				rest(dat,lex);
				
			}
			else			{
				System.out.println("idenifier expected in expression in line "+dat.line_no);
				do{
					dat.token = lex.lexer(dat);
				}while(!dat.token.toString().equals(";"));			}
			
		}
	}
	
	/*
	
	The rest function parses the rest of expression after the variable.
	like in the expression A=B+C
	rest check the syntax of the " + C " statement after the main starting phrase.
	*/
	public static void rest(data dat,Lexer lex)
	{
		if((dat.code == 4)&&((dat.token.toString().equalsIgnoreCase("+"))||(dat.token.toString().equalsIgnoreCase("-"))||(dat.token.toString().equalsIgnoreCase("/"))||(dat.token.toString().equalsIgnoreCase("*"))))
		{
			dat.token = lex.lexer(dat);
			
			expression(dat,lex);
		}
		else
		{	
			
			//System.out.println("the syntax is fine in rest "+dat.line_no);
		}
	}




}
